package com.thinkgem.jeesite.modules.magnetic.util;

import com.thinkgem.jeesite.modules.intelligent.entity.IntelligentController;
import com.thinkgem.jeesite.modules.intelligent.service.IntelligentControllerService;
import com.thinkgem.jeesite.modules.lane.entity.Lane;
import com.thinkgem.jeesite.modules.lane.service.LaneService;
import com.thinkgem.jeesite.modules.previous_flow.entity.PreviousFlow;
import com.thinkgem.jeesite.modules.previous_flow.service.PreviousFlowService;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
import java.util.List;

/**
 * @author xlp
 * @date 2019/4/28
 * 客户端接收数据
 */
@Component
public class TCPClient implements Runnable{

    private Logger log = Logger.getLogger(TCPClient.class);//输出Log日志

    private static final int PORT = 26;
    private static final String Address = "192.168.0.7";

    @Autowired
    private LaneService laneService;

    @Autowired
    private SignLightControl signLightControl;

    @Autowired
    private PreviousFlowService flowService;

    @Autowired
    private IntelligentControllerService intelligentService;

    @Override
    public void run() {
        Socket socket = null;
        try {
            ServerSocket serverSocket = new ServerSocket(PORT);
            socket = serverSocket.accept();
            InputStream is = socket.getInputStream();
            BufferedInputStream bis = new BufferedInputStream(is);
            DataInputStream dis = new DataInputStream(bis);
            byte[] b = new byte[1];     //一次只读取一个byte
            String ret = "";
            while (dis.read(b)!=-1){
                ret += bytesToHexString(b) + " ";
                if (dis.available() == 0) { //一个请求
                    log.info( "捕获的信息:" + ret.toUpperCase());
                    //处理数据
                    ret = ret.toUpperCase().replace(" ", "");
                    String[] arr = ret.split("A509");
                    for (int i = 0; i<arr.length; i++){
                        if (!StringUtils.isEmpty(arr[i])&&arr[i].length()==26){
                            String str = arr[i];
                            //判断是否有车经过
                            String judgeNum = str.substring(6,8);
                            if ("62".equals(judgeNum)){
                                //记录车道号
                                long laneNum1 = Long.parseLong(str.substring(8,10), 16);
                                long laneNum2 = Long.parseLong(str.substring(10,12), 16);
                                String laneNum = String.valueOf(laneNum1).concat(String.valueOf(laneNum2));
                                log.info("车道号:"+laneNum);
                                //获取进入的车流量和离开的车流量
                                long enterFlow = Long.parseLong(str.substring(16,18), 16);
                                long leaveFlow = Long.parseLong(str.substring(18,20), 16);
                                log.info("进入的车流量:" + enterFlow + "离开的车流量:" + leaveFlow);
                                //计算本次车辆经过的数量变化，并保存本次的进、出车流量
                                long change = getCarChangeNum(laneNum, enterFlow, leaveFlow);
                                //根据车道号更新各车道的剩余车位,以及根据当前剩余车位控制红灯亮或绿灯亮
                                updateRemainSpace(laneNum, change);
                            }
                        }
                    }
                    ret = "";
                }
            }
            log.info("client is over");
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     *
     * @param laneNum   车道号
     * @param enterFlow 当前进入的车流量
     * @param leaveFlow 当前离开的车流量
     * @return
     */
    public long getCarChangeNum(String laneNum, long enterFlow, long leaveFlow){
        //根据车道号查询上一次的进入、离开的车流量
        PreviousFlow previousFlow = new PreviousFlow();
        previousFlow.setLaneNum(laneNum);
        List<PreviousFlow> list = flowService.findList(previousFlow);
        //计算本次进入和离开的车辆变化值
        long enterChange = 0;
        long leaveChange = 0;
        //如果未查询到，说明本次为首次车辆进出该车道
        if (CollectionUtils.isEmpty(list)||list.get(0)==null){
            previousFlow.setLaneNum(laneNum);

            enterChange = enterFlow;
            leaveChange = leaveFlow;

        }else {
            //上一次进入车道的流量
            long lastEnterNum = list.get(0).getLastEnterFlow();
            //上一次离开车道的流量
            long lastLeaveNum = list.get(0).getLastLeaveFlow();

            previousFlow.setId(list.get(0).getId());

            //如果断电了，则地磁的流量会清零，那么上一次进或出的流量无法比较，则车道经过的车数量就等于断电后的地磁流量
            if (enterFlow<lastEnterNum){
                enterChange = enterFlow;
            }else {
                enterChange = enterFlow - lastEnterNum;
            }
            if (leaveFlow<lastLeaveNum){
                leaveChange = leaveFlow;
            }else {
                leaveChange = leaveFlow - lastLeaveNum;
            }
        }
        log.info("进入的车辆数:" + enterChange + "离开的车辆数:" + leaveChange);
        //如果进或出的流量达到255，则需要清零，这个时候表previousFlow中对应的进或出也要清零
        if(enterFlow==255){
            previousFlow.setLastEnterFlow(0);
        }else {
            previousFlow.setLastEnterFlow((int)enterFlow);
        }
        if (leaveFlow==255){
            previousFlow.setLastLeaveFlow(0);
        }else{
            previousFlow.setLastLeaveFlow((int)leaveFlow);
        }
        flowService.save(previousFlow);

        long change = leaveChange - enterChange;
        return change;
    }

    /**
     * 根据车道号更新各车道的剩余车位,以及根据当前剩余车位控制红灯亮或绿灯亮
     */
    public void updateRemainSpace(String laneNum, long change){
        Lane lane = new Lane();
        lane.setLaneNum(laneNum);
        List<Lane> laneList = laneService.findList(lane);
        if (!CollectionUtils.isEmpty(laneList)){
            //获取该车道引导灯的智能控制
            IntelligentController intelligent = new IntelligentController();
            intelligent.setLightId(laneList.get(0).getId());
            List<IntelligentController> intelligentList = intelligentService.findList(intelligent);
            //计算本次车道剩余车位
            lane = laneList.get(0);
            lane.setRemainSpace(String.valueOf(Long.valueOf(lane.getRemainSpace())+change));
            //如果车道剩余车位为0,则关闭绿灯，打开红灯
            if ("0".equals(lane.getRemainSpace())){
                /*if (!CollectionUtils.isEmpty(intelligentList)){
                    intelligent = intelligentList.get(0);
                    if ("A".equals(intelligent.getStatus())){
                        signLightControl.controlSighLight(signLightControl.OFF_GREEN);
                        signLightControl.controlSighLight(signLightControl.OPEN_RED);
                    }
                }*/
                lane.setUpdateTime(new Date());
                laneService.save(lane);
            }
            //如果计算后的剩余车位<0,则关闭绿灯，打开红灯并且数据库中剩余车位始终为0
            if (Long.valueOf(lane.getRemainSpace())<0){
                /*if (!CollectionUtils.isEmpty(intelligentList)){
                    intelligent = intelligentList.get(0);
                    if ("A".equals(intelligent.getStatus())){
                        signLightControl.controlSighLight(signLightControl.OFF_GREEN);
                        signLightControl.controlSighLight(signLightControl.OPEN_RED);
                    }
                }*/
            }
            //如果该车道剩余车位大于0并且小于等于总车位,则关闭红灯，打开绿灯
            if(Long.valueOf(lane.getRemainSpace())>0&&
                    Long.valueOf(lane.getRemainSpace())<=Long.valueOf(lane.getTotalSpace())){
                /*if (!CollectionUtils.isEmpty(intelligentList)){
                    intelligent = intelligentList.get(0);
                    if ("A".equals(intelligent.getStatus())){
                        signLightControl.controlSighLight(signLightControl.OFF_RED);
                        signLightControl.controlSighLight(signLightControl.OPEN_GREEN);
                    }
                }*/
                lane.setUpdateTime(new Date());
                laneService.save(lane);
            }
        }
    }

    /**
     * 将数组转16进制
     * @param bytes
     * @return
     */
    public static String bytesToHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(0xFF & bytes[i]);
            if (hex.length() == 1) {
                sb.append('0');
            }
            sb.append(hex);
        }
        return sb.toString();
    }


    /**
     * 将十六进制的字符串转换成字节数组
     *
     * @param hexString
     * @return
     */
    public static byte[] hexStrToBinaryStr(String hexString) {

        if (StringUtils.isEmpty(hexString)) {
            return null;
        }

        hexString = hexString.replaceAll(" ", "");

        int len = hexString.length();
        int index = 0;

        byte[] bytes = new byte[len / 2];

        while (index < len) {

            String sub = hexString.substring(index, index + 2);

            bytes[index/2] = (byte)Integer.parseInt(sub,16);

            index += 2;
        }
        return bytes;
    }

}
